Software Design X-Rays
https://gyazo.com/a78ddd26e55afa2bbf7cfdbfed5658d3
It's not techinical debt unless we have to pay interest on it, and intereset rate is a function of time
読むのに注意を払わないといけない場合だけ秘術的負債と呼ぶ。注意を払う行為は時間が密接に関係してくる
the root cause is often social and organizational problems
真の原因は、人間や組織的な問題であることが多い
Behavioral Code Analysis
コード自体ではなく、バージョン管理に保存されているデータからコードを時間軸も含めて解析する方法。
主に負債になってる箇所や原因、また負債の重み付けなどを行うための解析。
Interest Rates
Code Frequency
ほとんどのソースコードは、縦軸を変更の回数としたときに以下のような long tail グラフになる
https://gyazo.com/579df48ca3be78b0d9d50046609f70f8
code:proxy interest rate
# commitの回数が多いファイル一覧を出力
git log --format=format: --name-only | egrep -v '^$' | sort | uniq -c | sort -r | head -5
# commitの回数が多いファイル一覧をファイルに出力
git log --format=format: --name-only | egrep -v '^$' | sort | uniq -c | sort -r > all_frequesncies.txt
Complexity Dimension
コードが多く変更されるというだけではそこが読むのが難しいとまでは言えない、変更の頻度が多くて複雑なコードを探したい
ifやelseを数える代わりにインデントの数を数えるという方法
Function Level Analysis
Interest Ratesの測定により着目すべきファイルを特定したあと、そのファイルの詳細についてさらに調べていきたい
XRay Analysis
1. 着目すべきファイルの履歴を git から持ってくる
2. 全ての連続するバージョン間で git diff を取る
3. diffで変更された関数を取り出す
4. 関数ごとに change fequency をまとめて関数ごとに出す
Change Coupling
同一のcommit内で一緒に変更したファイルを調査することも発見がある
同一のcommitの中で変更しないといけないということは、それらのファイルは密接に関係していると言える
この本の中では、以下の条件を満たしてるものを change coupling としている
少なくとも20回のコミットで一緒に変わる
ファイルは、いずれかのファイルに対して行われた合計コミットの少なくとも50%で一緒に変更される
Software Clones
類似度が高くコピペによるコードを探すこともリファクタリングの最初の一歩になる
一般的にどんなソフトウェアにも5-20%の割合でコードの複製が存在しているとも言われてる
Code Similarity によって測定されることが多い
Future Hot Spot Analysis
code: bash
# 二ヶ月前
git log --before="two months ago" --format=format: --name-only | egrep -v '^$' | sort | uniq -c | sort -r > two_months_ago.txt
# 今
git log --format=format: --name-only | egrep -v '^$' | sort | uniq -c | sort -r > now.txt
# two_months_ago.txt と now.txt を比較して急上昇中のhot spotをみる
Refactoring Strategies
Principle of Proximity
近いものは、グループとしてまとめて捉えるというゲシュタルト心理学に基づく
同じようなものは、近い場所に移動するというリファクタリング戦略
また逆にChange Coupling functionであっても、距離が遠い場合には抽象化できないかもしれないことを示す
Splinter Pattern
1つのファイルが巨大でリファクタリング対象になってる場合には細かくファイルを分ける
コンフリクトを避ける
意味のあるまとまりとしてコードを分割する
アルゴリズム
1. テストが十分あるか?(なければE2Eテストを一時的に作る)
わざわざ自動テストを書かなくても、手動でも問題ないかもしれない (一時的なテストはどうせ寿命が短いので)
2. コードを理解して役割によって分類をする
3. Proximity Refactoringを行い、ファイル内で意味のあるまとまりに移動していく
4. 別のモジュールに移動する
5. 新しいモジュールの呼び出しに変更する (Delegate する)
6. 1で用意していたリグレッションテストを実行して動作が変わっていないことを確かめる
7. 次の対象を選び4からやり直す
Stabilize Code by Age
コードには、アクティブに更新されている箇所とstableになってしばらく変更がない部分がある
stable
コードの役割が落ち着いている
ブラックボックスとしてみなすことが開発者が考えることを減らす
長い間、稼働していて研究からもバグの確率が小さいことが知られている
コードは、very recent, old, middle があり、middleなコードが最も開発者にとって読むのが難しい
アルゴリズム
1. 直近変更されていないファイルとアクティブに開発されている箇所で分類する
2. stableになっているものは別のパッケージやライブラリにして物理的に分離する
3. stablizeに失敗しているコードを移動したり、リファクタリングする
calculate the age og code
1. git ls-files でリポジトリの全てのファイルを取得する
2. git log -1 --format="%ad" --date=short -- FILEPATH で最後にcommitがあった日付を取得する
3. どれくらい最後のcommitから経ってるかを計算する
Devide and Conquer
これまでファイル単位、関数単位で解析を行ってきたが、これをモジュール単位、サブシステム単位で行うようにしていく
アルゴリズム
1. Architectural boundaries を見つける
2. 1のレベルでhot spot analysisを行う
3. hot spotに含まれるファイルそれぞれをまた詳細解析する
観点
commit frequency
complexity
Lines of code
Similalirty
Coupling
軸
時間軸
組織的観点
コードを見ただけでは、生産性のボトルネックになってるかどうかはわからない
アーキテクチャの成功は、新しいフィーチャーをフィーチャーを開発している人たちだけで完結して開発できること
モジュールの境界をチームの責任に合わせていく
モジュールを分けるだけでは不十分
いわゆる コンウェイの法則
組織のメトリクスがソフトウェアの品質を測定する上でコードのメトリクスよりも有用であるという観測
authorの数、ex-authorの数など
Fractal Value Analysis
Authorが多いほどバグの可能性が増えるという観測
$ 1- \sum_{a_{i} \in \mathrm{A}} (\frac{nc(a_{i})}{NC})^2
$ \mathrm{A} : represents all authors that worked on the module
$ nc(a_{i}) : The number of commits by author a
$ NC : total number of commits for the module
どれくらいの人数がどれくらいのコードを書いてるかという指標
Fractal Value とバグの報告は強い相関があるという研究がある
Use Case and Feature-Centric
Package by Component vs Package by Feature
Componentごとにまとめると、一貫性が保てるが機能によって規模が異なるので小さい機能なのにも関わらず多くのファイルを要することもある
Featureごとにまとめると、そのFeatureの中ではある程度の自由を得ることができる
ただしFeatureを跨いでコードをシェアするということが難しくなってしまうというトレードオフが存在する
DCI (data, context and interaction) という戦略もある
感想
コード自体の解析ではなく、開発者のsocial activity を解析対象にするのは面白い視点だった
結局結論としては、
Hot Spot Analysis でコード中でアクティブに開発されていて、負債が溜まってる箇所を優先的にリファクタリングする
Code Frequency、Loc、Coupling で Hot Spotを見つける
そのファイルの Loc と Complexity を時間軸で追う
メソッドについても Code Frequency、Loc、Coupling が使える
Ageも意識することでコードのアクティブな部分とStableな部分を認識する
コンウェイの法則にしたがってコードの境界を設けていって、チームでオーナーシップを持つようにして Operational Boundariesを狭くする (Knowledge Boundariesは広いままを保つ)
いろんな人がみんなでコードを書くとバグの確率が増えちゃうよ (Fractal Valueは小さい値を保てるようにしよう)
Code SceneやCode Maatの宣伝にも見える笑